package sms;

import java.time.LocalDate;
import java.util.*;


/*
需求:
1.将学号-学生对象存入HashMap,提供一个方法可以直接根据学号获取学生信息
2.获取指定科目最高成绩的学生信息
3.获取指定科目最低成绩的学生信息
*/
//使用Collection和泛型重构学生信息管理系统
public class StudentManagementSystem03 {
    private ArrayList<Student> students = new ArrayList<>();

    /**
     * 统计指定科目下不同成绩的学生人数
     * @param subject 指定科目
     * @return 不同成绩的学生人数统计
     */
    public Map<Integer, Integer> getScoreStatisticsBySubject(String subject){
        HashMap<Integer, Integer> scoreStatistics = new HashMap<>();
        for(Student student:students){
            int score = getScoreBySubject(student, subject);
            if(scoreStatistics.containsKey(score)){
                scoreStatistics.put(score, scoreStatistics.get(score) + 1);
            }else {
                scoreStatistics.put(score, 1);
            }
        }
        return scoreStatistics;
    }

    public Student findStudentWithHighestScore(String subject){
        return Collections.max(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return getScoreBySubject(o1, subject) - getScoreBySubject(o2, subject);
            }
        });
    }


    public Student findStudentWithLowestScore(String subject){
        return Collections.min(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return getScoreBySubject(o1, subject) - getScoreBySubject(o2, subject);
            }
        });
    }


    public void sortByTotalScore(){
        /*//1.构建一个TreeSet并且利用比较器指定比较规则
        TreeSet<Student> temps = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                //如果两个学生总分相同,但是姓名不同 导致另外一个学生无法存入TreeSet
                // 会导致   张三 158  李四 158,只存储一个人
                //return o2.getTotalScore() - o1.getTotalScore();
                int result = o2.getTotalScore() - o1.getTotalScore();
                if (result == 0) {
                    int nameResult = o2.getName().compareTo(o1.getName());
                    if (nameResult == 0) {
                        //如果总分相同,再去比较姓名
                        //比较总分和姓名可能出现 总分相同 姓名也相同
                        //例如: 2021137 王五 158  2021128 王五 158
                        return o2.getStudentId() - o1.getStudentId();
                    } else {
                        //总分相同,但是姓名不同
                        return nameResult;
                    }
                } else {
                    return result; //总分不同,不再比较次要条件
                }
            }
        });

        temps.addAll(students);//将指定的集合中的元素拷贝到当前集合,相当于将ArrayList中的元素拷贝到TreeSet中
        students.clear();//清空系统中原有的元素
        students.addAll(temps);//再把TreeSet中按照总分排好序的元素放回ArrayList中*/

        students.sort(new Comparator<Student>() {
            //JDK8以后的版本可用
            @Override
            public int compare(Student o1, Student o2) {
                return o2.getTotalScore() - o1.getTotalScore();//List集合允许存重复元素,因此不需要比较次要条件,所有的元素都会存入
            }
        });
    }
    /**
     *
     * @param number 学生的编号(从1开始)
     * @param newStudent 学生的新的信息(学生对象中封装新的信息)
     * @return 更改前的学生对象
     */
    public Student updateStudentByIndex(int number, Student newStudent) {
        if (number >= 1 && number <= students.size()) {
            return students.set(number - 1, newStudent);
        }else{
            System.out.println("不存在序号为:" + number + "的学生信息");
            return null;
        }
    }


    /**
     *
     * @return 随机取到的学生
     */
    public Student randomRollCall(){
/*        Random random = new Random();
        int randomindex = random.nextInt(students.size());
        return students.get(randomindex);*/
        return students.get(new Random().nextInt(students.size()));
    }

    /**
     * 添加学生
     * @param student
     */
    public void addStudent(Student student){
        if (student != null && validateStudentEmail(student)) {
            students.add(student);
        } else {
            System.out.println("学号:" + student.getStudentId()
                    + ", 姓名:" + student.getName() + ", 电子邮件:"
                    + student.getEmail() + ", 不符合邮箱格式添加失败！");
        }
    }


    public boolean validateStudentEmail(Student student){
        if(student==null||student.getEmail()==null){
            return false;
        } else {
            return student.getEmail().matches("\\w+@\\w+\\.\\w+");
        }
    }


    public void showAllStudents(Collection<Student> students){
        int i = 1;
        for (Student student:students) {
            //if (students != null) 不用再做健壮性判断,添加学生时已经做了
                System.out.println((i++) + " " + student);
        }
    }


    public void showAllStudents(){
        showAllStudents(students);
    }


    public boolean contains(Student stu){
        return students.contains(stu);
    }


    public Student findStudentById(int studentId){
        for (Student student:students) {
            if ( student.getStudentId() == studentId) {
                return student;
            }
        }
        return null;
    }


    public int getAverageScoreBySubject(String subject){
        int totalScore = 0;
        for (Student student:students) {
                int score = getScoreBySubject(student, subject);
                totalScore += score;
        }
        return students.size() == 0 ? 0 : totalScore / students.size();
    }


    private int getScoreBySubject(Student student, String subject) {
        switch (subject){
            case "语文" -> {
                return student.getChineseScore();
            }
            case "数学" ->{
                return student.getMathScore();
            }
            case "历史" ->{
                if(student instanceof MiddleStudent middleStudent){//历史物理成绩为中学生特有，用instanceof关键词判断是否为中学生在返回成绩
                    return ((MiddleStudent) student).getHistoryScore();
                }
            }
            case "物理" ->{
                if(student instanceof MiddleStudent middleStudent){
                    return ((MiddleStudent) student).getPhysicsScore();
                }
            }

        }
        return 0;
    }


    public Collection<Student> getStudentsEnrolledBefore(String date){
        //1.定义一个集合来存放满足条件的学生
        Collection<Student> temps = new ArrayList<>();

        //2.遍历students中的每个学生,逐个判断
        //如果该学生的入学日期在指定日期之前,我们就将该学生存入temps数组中
        for (Student student:students) {
            if (student.getEnrollmentDates() != null) {
                if (student.getEnrollmentDates().isBefore(LocalDate.parse(date)) || student.getEnrollmentDates().isEqual(LocalDate.parse(date))) {
                    temps.add(student);
                }
            }
        }
        return temps;
    }


    public Collection getStudentsEnrolledAfter(String date){
        //1.定义一个集合来存放满足条件的学生
        Collection<Student> temps = new ArrayList();

        //2.遍历students中的每个学生,逐个判断
        //如果该学生的入学日期在指定日期之前,我们就将该学生存入temps数组中
        for (Student student:students) {
            if (student.getEnrollmentDates() != null) {
                if (student.getEnrollmentDates().isAfter(LocalDate.parse(date)) || student.getEnrollmentDates().isEqual(LocalDate.parse(date))) {
                    temps.add(student);
                }
            }
        }
        return temps;
    }
}
